<html>
<head><meta charset="utf-8"><title>VecDeque vs Stacked Borrows · t-lang/wg-unsafe-code-guidelines · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/index.html">t-lang/wg-unsafe-code-guidelines</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/VecDeque.20vs.20Stacked.20Borrows.html">VecDeque vs Stacked Borrows</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="163642605"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/VecDeque%20vs%20Stacked%20Borrows/near/163642605" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/VecDeque.20vs.20Stacked.20Borrows.html#163642605">(Apr 18 2019 at 11:35)</a>:</h4>
<p>And another Stacked Borrows violation in <code>VecDeque::drain</code>: <a href="https://github.com/rust-lang/rust/issues/60076" target="_blank" title="https://github.com/rust-lang/rust/issues/60076">https://github.com/rust-lang/rust/issues/60076</a></p>



<a name="163737311"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/VecDeque%20vs%20Stacked%20Borrows/near/163737311" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/VecDeque.20vs.20Stacked.20Borrows.html#163737311">(Apr 19 2019 at 14:04)</a>:</h4>
<p>This is interesting because it is the first time I found a conflict between existing code and the notion of "barriers". I think without barriers there would be no issue.</p>



<a name="163737451"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/VecDeque%20vs%20Stacked%20Borrows/near/163737451" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/VecDeque.20vs.20Stacked.20Borrows.html#163737451">(Apr 19 2019 at 14:06)</a>:</h4>
<p>This is a bit like</p>
<div class="codehilite"><pre><span></span><span class="k">struct</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="n">NoCopy</span><span class="p">(</span><span class="n">T</span><span class="p">);</span><span class="w"></span>
<span class="k">fn</span> <span class="nf">foo</span><span class="p">(</span><span class="k">mut</span><span class="w"> </span><span class="n">x</span>: <span class="nc">NoCopy</span><span class="o">&lt;&amp;</span><span class="kt">i32</span><span class="o">&gt;</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">  </span><span class="kd">let</span><span class="w"> </span><span class="n">ptr</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">&amp;</span><span class="n">x</span><span class="p">.</span><span class="mi">0</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="o">*</span><span class="k">const</span><span class="w"> </span><span class="kt">i32</span><span class="p">;</span><span class="w"></span>
<span class="w">  </span><span class="n">drop</span><span class="p">(</span><span class="n">x</span><span class="p">);</span><span class="w"> </span><span class="c1">// &quot;consume&quot; the shared reference</span>
<span class="w">  </span><span class="o">*</span><span class="p">(</span><span class="n">ptr</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="o">*</span><span class="k">mut</span><span class="w"> </span><span class="n">U</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">...;</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</pre></div>


<p>The <code>NoCopy</code> wrapper here changes nothing, and without that this is clearly UB.</p>



<a name="163737472"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/VecDeque%20vs%20Stacked%20Borrows/near/163737472" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/VecDeque.20vs.20Stacked.20Borrows.html#163737472">(Apr 19 2019 at 14:06)</a>:</h4>
<p>Cc <span class="user-mention" data-user-id="116009">@nikomatsakis</span> this relates to the question of whether to traverse below private fields or not</p>



<a name="163763052"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/VecDeque%20vs%20Stacked%20Borrows/near/163763052" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/VecDeque.20vs.20Stacked.20Borrows.html#163763052">(Apr 19 2019 at 20:34)</a>:</h4>
<p>uh, actually <code>RefCell</code> has the same problem...</p>
<div class="codehilite"><pre><span></span><span class="k">use</span><span class="w"> </span><span class="n">std</span>::<span class="n">cell</span>::<span class="p">{</span><span class="n">RefCell</span><span class="p">,</span><span class="w"> </span><span class="n">Ref</span><span class="p">};</span><span class="w"></span>

<span class="k">fn</span> <span class="nf">break_it</span><span class="p">(</span><span class="n">rc</span>: <span class="kp">&amp;</span><span class="nc">RefCell</span><span class="o">&lt;</span><span class="kt">i32</span><span class="o">&gt;</span><span class="p">,</span><span class="w"> </span><span class="n">r</span>: <span class="nc">Ref</span><span class="o">&lt;</span><span class="na">&#39;_</span><span class="p">,</span><span class="w"> </span><span class="kt">i32</span><span class="o">&gt;</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="c1">// `r` has a shared reference, it is passed in as argument and hence</span>
<span class="w">    </span><span class="c1">// a barrier is added that marks this memory as read-only for the entire</span>
<span class="w">    </span><span class="c1">// duration of this function.</span>
<span class="w">    </span><span class="n">drop</span><span class="p">(</span><span class="n">r</span><span class="p">);</span><span class="w"></span>
<span class="w">    </span><span class="c1">// *oops* here we can mutate that memory.</span>
<span class="w">    </span><span class="o">*</span><span class="n">rc</span><span class="p">.</span><span class="n">borrow_mut</span><span class="p">()</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">2</span><span class="p">;</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">rc</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">RefCell</span>::<span class="n">new</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span><span class="w"></span>
<span class="w">    </span><span class="k">break</span><span class="n">_it</span><span class="p">(</span><span class="o">&amp;</span><span class="n">rc</span><span class="p">,</span><span class="w"> </span><span class="n">rc</span><span class="p">.</span><span class="n">borrow</span><span class="p">())</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</pre></div>



<a name="163763194"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/VecDeque%20vs%20Stacked%20Borrows/near/163763194" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/VecDeque.20vs.20Stacked.20Borrows.html#163763194">(Apr 19 2019 at 20:36)</a>:</h4>
<p>actually <span class="user-mention" data-user-id="198590">@comex</span> <a href="https://internals.rust-lang.org/t/stacked-borrows-an-aliasing-model-for-rust/8153/12" target="_blank" title="https://internals.rust-lang.org/t/stacked-borrows-an-aliasing-model-for-rust/8153/12">predicted this long ago</a> but it seems I kind of forgot about it <em>oops</em></p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>